package net.hashcoding.cookbook.core;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * Created by Administrator on 2017/6/25.
 */
public abstract class Service {

    protected abstract HttpServletRequest handle(HashMap<String, Object> environment,
                                        HttpServletRequest request);

    protected static Service factory(Class<? extends Service> clazz) {
        // TODO:
        try {
            return clazz.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
            throw ServiceException.internalError();
        }
    }

    public static void register(Class<? extends Service> clazz) {
        ServiceManager manager = ServiceManager.getInstance();
        manager.register(clazz);
    }

    public static HttpServletRequest process(HashMap<String, Object> environment,
                                             HttpServletRequest request) {
        ServiceManager manager = ServiceManager.getInstance();
        return manager.process(environment, request);
    }

    private static class ServiceManager {
        private static volatile ServiceManager manager;

        private static ServiceManager getInstance() {
            if (manager ==  null) {
                synchronized(ServiceManager.class) {
                    if (manager == null)
                        manager = new ServiceManager();
                }
            }
            return manager;
        }

        private List<Service> services;

        private ServiceManager() {
            services = new ArrayList<>();
        }

        void register(Class<? extends Service> clazz) {
            services.add(Service.factory(clazz));
        }

        private HttpServletRequest process(HashMap<String, Object> environment,
                                           HttpServletRequest request) {
            for (Service service : services) {
                request = service.handle(environment, request);
            }
            return request;
        }
    }


}
